package com.ho1ho.audioexample.tcp;

import android.util.Log;

import com.ho1ho.audioexample.utils.others.ByteUtil;

import java.util.Arrays;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * Created by Michael Leo <y@ho1ho.com><br>
 * Date: 2020/02/05 13:35
 * <p>
 * Code is far away from bug with the animal protecting
 * </p>
 * <pre>
 * ----------Dragon be here!----------/
 *    ┏┓   ┏┓
 *   ┏┛┻━━━┛┻┓
 *   ┃       ┃
 *   ┃   ━   ┃
 *   ┃ ┳┛ ┗┳ ┃
 *   ┃       ┃
 *   ┃   ┻   ┃
 *   ┃       ┃
 *   ┗━┓   ┏━┛
 *     ┃   ┃神兽保佑
 *     ┃   ┃代码无BUG！
 *     ┃   ┗━━━┓
 *     ┃       ┣┓
 *     ┃       ┏┛
 *     ┗┓┓┏━┳┓┏┛
 *      ┃┫┫ ┃┫┫
 *      ┗┻┛ ┗┻┛
 * ━━━━━━神兽出没━━━━━━
 * </pre>
 */
public class TcpClient {
    private static final String TAG = TcpClient.class.getSimpleName();
    //    public static String HOST = "127.0.0.1";
    public static int PORT = 9999;

    public Bootstrap bootstrap;// = getBootstrap();
    public Channel channel;// = getChannel(HOST, PORT);

    public void initClient(String host) {
        bootstrap = getBootstrap();
        channel = getChannel(host, PORT);
    }

    /**
     * 初始化Bootstrap
     */
    public Bootstrap getBootstrap() {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(group)
                .channel(NioSocketChannel.class);
        b.handler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
//                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
//                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
//                pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
//                pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
//                pipeline.addLast("messageDecoder", new FirstIntLeDecoder());
                pipeline.addLast(new LoggingHandler(LogLevel.DEBUG));

//                ByteBuf delimiter = Unpooled.copiedBuffer("$_$".getBytes());
//                pipeline.addLast("messageDecoder", new DelimiterBasedFrameDecoder(1024 * 1024, delimiter));

//                pipeline.addLast("messageDecoder", new FirstIntLeDecoder());
                pipeline.addLast("handler", new TcpClientHandler());
            }
        });
        b.option(ChannelOption.SO_KEEPALIVE, true);
        return b;
    }

    public Channel getChannel(String host, int port) {
        Channel channel = null;
        try {
            channel = bootstrap.connect(host, port).sync().channel();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, String.format("连接Server(IP %s,PORT %d)失败", host, port));
            return null;
        }
        return channel;
    }

    public void sendMsg(String msg) throws Exception {
        if (channel != null) {
            channel.writeAndFlush(msg).sync();
        } else {
            Log.w(TAG, "消息发送失败,连接尚未建立!");
        }
    }

    public void sendData(byte[] bytes) throws Exception {
//        Log.i(TAG, "Sending data 1: " + Arrays.toString(bytes));
        if (channel != null) {
            byte[] all = ByteUtil.mergeBytes(ByteUtil.int2Bytes(bytes.length), bytes);
            Log.i(TAG, "Sending data [" + all.length + "|" + bytes.length + "]: " + Arrays.toString(all));
            channel.writeAndFlush(Unpooled.wrappedBuffer(all)).sync();
        } else {
            Log.w(TAG, "消息发送失败,连接尚未建立!");
        }
    }

//    public static void main(String[] args) throws Exception {
//        try {
//            long t0 = System.nanoTime();
//            for (int i = 0; i < 100; i++) {
//                TcpClient.sendMsg(i + "你好1");
//            }
//            long t1 = System.nanoTime();
//            Log.i(TAG, "time used:" + (t1 - t0));
//        } catch (Exception e) {
//            Log.e(TAG, "main err:", e);
//        }
//    }
}
